package applyMath

import (
	"fmt"
)

//检查字符串括号是否匹配
//（123)[]{{}}  ---> true
// (das))[123]{df} ----> false
// {(456})这种 栈最好判断，其他方式可能判断错误。
func CheckBracketTest() {
	//str := "(123)[]{{}}"
	str := "())[]{}"
	//str := `{(})[]`
	fmt.Printf("is correct %t\n", checkMatchingBracket(str))
	fmt.Printf("is correct %t\n", checkMatchingBracketForCount(str))
	m := NewStack()
	fmt.Printf("is correct %t\n", m.checkMatchingBracketForStack(str))
}

func checkMatchingBracket(s string) bool {
	a1 := make([]rune, 0)
	a2 := make([]rune, 0)
	a3 := make([]rune, 0)
	for _, v := range s {
		switch v {
		case 40:
			a1 = append(a1, v)
		case 41:
			length := len(a1)
			if length == 0 {
				return false
			}
			a1 = a1[0 : length-1]
		case 91:
			a2 = append(a2, v)
		case 93:
			length := len(a2)
			if length == 0 {
				return false
			}
			a2 = a2[0 : length-1]
		case 123:
			a3 = append(a3, v)
		case 125:
			length := len(a3)
			if length == 0 {
				return false
			}
			a3 = a3[0 : length-1]
		}
	}
	if len(a1) != 0 || len(a2) != 0 || len(a3) != 0 {
		fmt.Println(a1, a2, a3)
		return false
	}
	return true
}

func checkMatchingBracketForCount(s string) bool {
	var a, b, c = 0, 0, 0
	for _, v := range s {
		switch v {
		case 40:
			a++
		case 41:
			if a == 0 {
				return false
			}
			a--
		case 91:
			b++
		case 93:
			if b == 0 {
				return false
			}
			b--
		case 123:
			c++
		case 125:
			if c == 0 {
				return false
			}
			c--
		}
	}
	if a != 0 || b != 0 || c != 0 {
		return false
	}
	return true
}

type Stack struct {
	count int
	stack []rune
}

func NewStack() *Stack {
	return &Stack{0, make([]rune, 0)}
}

func (m *Stack) Pop() rune {
	var pop rune
	m.count--
	if m.count == -1 {
		return 0
	}
	pop = m.stack[m.count]
	m.stack = m.stack[0:m.count]
	return pop
}

func (m *Stack) Push(s rune) rune {
	m.stack = append(m.stack, s)
	m.count++
	return s
}

func (m *Stack) checkMatchingBracketForStack(s string) bool {
	for _, v := range s {
		switch v {
		case 40, 91, 123:
			m.Push(v)
		case 41, 93, 125:
			temp := m.Pop()
			switch temp {
			case 40:
				if v != 41 {
					return false
				}
			case 91:
				if v != 93 {
					return false
				}
			case 123:
				if v != 125 {
					return false
				}
			default:
				return false
			}
		}
	}
	if m.count != 0 {
		return false
	}
	return true
}
